﻿#region Copyright(c) 2006 ZO, All right reserved.
// -----------------------------------------------------------------------------
// Copyright(c) 2006 ZO, All right reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//   1.  Redistribution of source code must retain the above copyright notice,
//       this list of conditions and the following disclaimer.
//   2.  Redistribution in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//   3.  The name of the author may not be used to endorse or promote products
//       derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// -----------------------------------------------------------------------------
#endregion


#region Using directives

using System;
using System.Diagnostics.CodeAnalysis;
using ArgumentNullException=ZO.SmartCore.Core.ArgumentNullException;

#endregion

namespace ZO.SmartCore.Xml
{
    /// <summary>
    /// Represents an attribute. 
    /// </summary>
    [SuppressMessage("Microsoft.Naming", "CA1711:IdentifiersShouldNotHaveIncorrectSuffix")]
    public class Attribute : Node
    {

        #region Constructors
        /// <summary>
        /// Initializes a new instance of the <see cref="Attribute"/> class.
        /// </summary>
        /// <param name="name">The name.</param>
        public Attribute(string name)
            : this(name, "", "")
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="Attribute"/> class.
        /// </summary>
        /// <param name="name">The name.</param>
        /// <param name="value">The text.</param>
        public Attribute(string name, string value)
            : this(name, value, "")
        {

        }

        /// <summary>
        /// Initializes a new instance of the <see cref="Attribute"/> class.
        /// </summary>
        /// <param name="name">The name.</param>
        /// <param name="value">The text.</param>
        /// <param name="prefix">The prefix.</param>
        public Attribute(string name, string value, string prefix)
        {
            if (String.IsNullOrEmpty(name))
            {
                throw new ArgumentNullException("name");
            } // if

            this._Name = name;


            if (!String.IsNullOrEmpty(value))
            {
                this._textValue = new Text(value);
                ChildNodes.Add(_textValue);
            }

            if (!(String.IsNullOrEmpty(prefix)))
            {
                this.Prefix = prefix;
            }
        }
        #endregion

        #region Destructor

        #endregion

        #region Fields
        private string _Name;

        internal Node parentElement;
        private string _Prefix;
        private Text _textValue;

        #endregion

        #region Events

        #endregion

        #region Operators

        #endregion

        #region Properties
        
        /// <summary>Gets the parent of this node (for nodes that can have parents).</summary>
        /// <returns>The Node that is the parent of the current node. If a node has just been created and not yet added to the tree, or if it has been removed from the tree, the parent is null. For all other nodes, the value returned depends on the <see cref="P:System.Xml.XmlNode.NodeType"></see> of the node. The following table describes the possible return values for the ParentNode property.NodeType Return Value of ParentNode Attribute, Document, DocumentFragment, Entity, Notation Returns null; these nodes do not have parents. CDATA Returns the element or entity reference containing the CDATA section. Comment Returns the element, entity reference, document type, or document containing the comment. DocumentType Returns the document node. Element Returns the parent node of the element. If the element is the root node in the tree, the parent is the document node. EntityReference Returns the element, attribute, or entity reference containing the entity reference. ProcessingInstruction Returns the document, element, document type, or entity reference containing the processing instruction. Text Returns the parent element, attribute, or entity reference containing the text node. </returns>
        public override Node Parent
        {
            get
            {
                return this.parentElement;
            }

        }
        /// <summary>Gets the qualified name of the node.</summary>
        /// <returns>The qualified name of the node. For XmlElement nodes, this is the tag name of the element.</returns>
        public virtual string Name
        {
            get
            {
                return this._Name;
            }
            //protected set
            //{
            //    _Name = value;
            //} // set
        }

        /// <summary>
        /// When overridden in a derived class, gets the type of the current node.
        /// </summary>
        /// <value></value>
        /// <returns>One of the <see cref="NodeType"></see> values.</returns>
        public override NodeType NodeType
        {
            get { return NodeType.Attribute; }
        }

        /// <summary>Gets or sets the namespace prefix of this node.</summary>
        /// <returns>The namespace prefix of this node. If there is no prefix, this property returns String.Empty.</returns>
        /// <exception cref="System.Xml.XmlException">The specified prefix contains an invalid character.The specified prefix is malformed.The namespaceURI of this node is null.The specified prefix is "xml" and the namespaceURI of this node is different from http://www.w3.org/XML/1998/namespace. </exception>
        /// <exception cref="System.ArgumentException">This node is read-only </exception>
        public string Prefix
        {
            get
            {
                return this._Prefix;
            }
            set
            {
                this._Prefix = value;
            }
        }

        /// <summary>
        /// Gets or sets the value of the node.
        /// </summary>
        /// <value></value>
        /// <returns>The value returned depends on the <see cref="NodeType"></see> of the node: Type Value Attribute The value of the attribute. CDATASection The content of the CDATA Section. Comment The content of the comment. Document null. DocumentFragment null. DocumentType null. Element null. You can use the <see cref="P:System.Xml.XmlElement.InnerText"></see> or <see cref="P:System.Xml.XmlElement.InnerXml"></see> properties to access the value of the element node. Entity null. EntityReference null. Notation null. ProcessingInstruction The entire content excluding the target. Text The content of the text node. SignificantWhitespace The white space characters. White space can consist of one or more space characters, carriage returns, line feeds, or tabs. Whitespace The white space characters. White space can consist of one or more space characters, carriage returns, line feeds, or tabs. XmlDeclaration The content of the declaration (that is, everything between &lt;?xml and ?&gt;). </returns>
        /// <exception cref="System.InvalidOperationException">Setting the value of a node that is not supposed to have a value (for example, an Element node). </exception>
        /// <exception cref="System.ArgumentException">Setting the value of a node that is read-only. </exception>
        public override string Value
        {
            get
            {
                if (_textValue != null)
                {
                    return _textValue.Value; 
                }
                return "";
            }
            set
            {
                if (!String.IsNullOrEmpty(value))
                {
                    if (_textValue == null)
                    {
                        this._textValue = new Text(value);
                        this.ChildNodes.Add(_textValue);
                    }
                    else
                    {
                        this._textValue.Value = value;
                    }
                }
                else
                {
                    if (_textValue != null)
                    {
                        this.ChildNodes.Remove(_textValue);
                    }

                }
            }
        }
        #endregion

        #region Methods
  
    
        /// <summary>
        /// Adds the specified node to the end of the list of child nodes, of this node.
        /// </summary>
        /// <param name="newChild">The node to add</param>
        /// <returns></returns>
        public override void AddChild(Node newChild)
        {
            if (newChild == null)
            {
                return;
            }

            if (newChild.NodeType == NodeType.Text)
            {
                this.Value = newChild.Value;
            }
        }

        #endregion
    }
}
